const jsonFormatFn = (val) => {
    /**
     * JSON的值可以是对象、数组、数字、字符串或者三个字面值(false、null、true)中的一个
     * 例如：'123','"abc"','false','null','true'是JSON字符串,可以JSON.parse成功
     * JSON对象、数组内的键值对的值和数组的元素也是由上述这几种值构成
     */

    switch (Object.prototype.toString.call(val)) {
        case "[object String]": //JSON字符串肯定是字符串类型
            try {
                let jsonObj = JSON.parse(val);
                switch (Object.prototype.toString.call(jsonObj)) {
                    case "[object Object]":
                    case "[object Array]":
                        //与服务器的数据交互中，只认为解析出对象和数组才认为有意义
                        return jsonObj;

                    default: //string number boolean null
                        //因为这个方法会递归调用，所以解析出其它类型的只认为是改变了数据类型(str -> number)，所以维持原状
                        return val;
                }
            } catch (e) {
                //不是JSON字符串
                return val;
            }

        default:
            return val;
    }
};

const enumFormatFn = (val) => {
    /**
     * 枚举对象有且仅有三个属性dictParam，displayName，dictKey；值在后端是泛型
     * */
    switch (Object.prototype.toString.call(val)) {
        case "[object String]":
            //枚举字符串
            try {
                let enumObj = JSON.parse(val);
                switch (Object.prototype.toString.call(enumObj)) {
                    case "[object Object]":
                        //不是枚举字符串的情况要回退JSON.parse操作
                        return enumFormatFn(enumObj) !== enumObj
                            ? enumFormatFn(enumObj)
                            : val;

                    default:
                        //肯定不是枚举字符串
                        return val;
                }
            } catch (e) {
                //不是JSON字符串
                return val;
            }

        case "[object Object]": {
            //枚举对象
            let keyList = Object.keys(val);
            if (
                keyList.length ===
                new Set(["dictParam", "displayName", "dictKey"].concat(keyList))
                    .size
            ) {
                //是枚举对象 除了'dictParam','displayName','dictKey'后端可能会加新的属性比如remark
                return val.dictParam;
            } else {
                return val;
            }
        }

        default:
            return val;
    }
};

const formatDeepData = (val, formatFn) => {
    val = formatFn(val);
    switch (Object.prototype.toString.call(val)) {
        case "[object Object]": {
            let keyArr = Object.keys(val);
            keyArr.forEach((prop) => {
                val[prop] = formatDeepData(val[prop], formatFn);
            });
            return val;
        }

        case "[object Array]": {
            return val.map((item) => formatDeepData(item, formatFn));
        }

        default:
            return val;
    }
};

export const serveDataFormat = {
    jsonFormat(val) {
        return formatDeepData(val, jsonFormatFn);
    },
    enumFormat(val) {
        return formatDeepData(val, enumFormatFn);
    },
};
